﻿namespace PillBox.Client.Framework
{
    using System;
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;

    public class FrameNavigation : INavigation
    {
        private Frame _frame;
        private object _viewModel;
        private Action _completedAction;

        public FrameNavigation(Frame frame)
        {
            this._frame = frame;
            this._frame.Navigating += Frame_Navigating;
            this._frame.Navigated += Frame_Navigated;
        }

        public object Content
        {
            get
            {
                return this._frame.Content;
            }
        }

        public void Navigate(object viewModel, Action completed)
        {
            Uri uri = ViewLocator.LocateUri(viewModel);

            if (this._frame.CurrentSource == uri)
            {
                completed();
            }
            else
            {
                this._viewModel = viewModel;
                this._completedAction = completed;
                this._frame.Navigate(uri);
            }
        }

        private void Frame_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("FrameNavigation - Navigating");
        }

        private void Frame_Navigated(object sender, NavigationEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Frame_Navigated");

            bool forceScreenSwap = false;

            if (this._viewModel == null)
            {
                forceScreenSwap = true;
                this._viewModel = ((FrameworkElement)e.Content).DataContext;
            }

            if (this._viewModel == null)
                return;

            if (!forceScreenSwap)
            {
                ViewModelBinder.Bind(this._viewModel, e.Content as DependencyObject);
                ((IScreen)this._viewModel).Activate();
            }
            else
            {
                Debug.Assert(this._viewModel is IScreen);

                var shell = IoC.GetInstance<IShell>();

                shell.OpenScreen(this._viewModel as IScreen);
            }

            this._viewModel = null;

            if (this._completedAction != null)
            {
                this._completedAction();

                this._completedAction = null;
            }
        }
    }
}